package com.zxjbyte.yiyi.server.config;

import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.zxjbyte.yiyi.framework.common.constant.Constant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.PropertySource;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.stereotype.Component;

import java.util.concurrent.*;

/**
 * @Author zhangxingjia
 * @Date 2023/7/7 20:08
 * @Version: 1.0
 */
@Slf4j
@Component
@EnableScheduling
@EnableAsync
@PropertySource(value = "/yiyi-default.properties", encoding = "utf-8")
public class ConsoleConfig {

    /**
     * 异步注解@Async自定义线程池, 避免使用的是Spring默认的线程池SimpleAsyncTaskExecutor
     *  使用方式：
     *      @Async("default-thread-pool")
     *
     * @return
     */
    @Bean(Constant.DEFAULT_THREAD_POOL)
    public Executor customAsyncExecutor(){
        // 创建线程工厂，配置线程池名称和线程优先级
        ThreadFactory threadFactory = new ThreadFactoryBuilder()
                .setNameFormat("my-thread-%d")
                .setPriority(Thread.NORM_PRIORITY)
                .setDaemon(false) // 非守护线程
                .build();
        int corePoolSize = Runtime.getRuntime().availableProcessors() * 2;
        int maximumPoolSize = Math.max(corePoolSize, 100);
        // 创建线程池，使用threadFactory工厂
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
                corePoolSize, // 核心线程数是线程池中一直保持存活的线程数量
                maximumPoolSize,  // 最大线程数是线程池中允许的最大线程数量
                60,          // 线程存活时间是非核心线程在空闲状态下被回收之前等待新任务的最长时间
                TimeUnit.SECONDS, // 存活时间单位指定了 keepAliveTime 的时间单位，通常为 TimeUnit.SECONDS
                new LinkedBlockingQueue<>(200),  // 工作队列用于存储等待执行的任务。
                threadFactory  // 线程工厂用于创建新线程
        );
        threadPool.setRejectedExecutionHandler((r, executor) -> {
            if(!executor.isShutdown()){ // 判断线程池是否已经关闭
                r.run();
            }
            log.warn("Match threadpool rejected handler(run now). >>>> Task {} rejected from {}",
                    r.toString() , executor.toString());
        });
        //允许核心线程超时
        threadPool.allowsCoreThreadTimeOut();
        return threadPool;
    }

}
